/*
 * Copyright (C) 2010 ZXing authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package lib_zxing.decoding;

import android.graphics.Bitmap;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;

import com.google.zxing.BinaryBitmap;
import com.google.zxing.DecodeHintType;
import com.google.zxing.MultiFormatReader;
import com.google.zxing.ReaderException;
import com.google.zxing.Result;
import com.google.zxing.common.HybridBinarizer;

import org.opencv.android.Utils;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.Point;
import org.opencv.core.RotatedRect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import aar.test.tessocr.tessOcrUtil.SimpleCallback;
import aar.test.tessocr.tessOcrUtil.TesseractUtil;
import clx.tessocr.ocreng.R;
import lib_zxing.activity.CaptureFragment;
import lib_zxing.camera.CameraManager;
import lib_zxing.camera.PlanarYUVLuminanceSource;

final class DecodeHandler extends Handler {

    private static final String TAG = DecodeHandler.class.getSimpleName();

    private final CaptureFragment fragment;

    private final MultiFormatReader multiFormatReader;

    private int index=0;

    private  boolean isScanning = false;

    private  List<RotatedRect> rects;


    DecodeHandler(CaptureFragment fragment, Hashtable<DecodeHintType, Object> hints) {
        multiFormatReader = new MultiFormatReader();
        multiFormatReader.setHints(hints);
        this.fragment = fragment;

    }

    @Override
    public void handleMessage(Message message) {
        if (message.what == R.id.decode) {
            decode((byte[]) message.obj, message.arg1, message.arg2);
        } else if (message.what == R.id.quit) {
            Looper.myLooper().quit();
        }
    }

    /**
     * Decode the data within the viewfinder rectangle, and time how long it took. For efficiency,
     * reuse the same reader objects from one decode to the next.
     *
     * @param data   The YUV preview frame.
     * @param width  The width of the preview frame.
     * @param height The height of the preview frame.
     */
    private void decode(byte[] data, int width, int height) {
//        long start = System.currentTimeMillis();
        Log.e(TAG, "decode0000000-------------------------00000000---------------------------isScanning=="+isScanning);
        if (!isScanning) {
            isScanning = true;
            //modify here
            byte[] rotatedData = new byte[data.length];
            for (int y = 0; y < height; y++) {
                for (int x = 0; x < width; x++)
                    rotatedData[x * height + height - y - 1] = data[x + y * width];
            }
            int tmp = width; // Here we are swapping, that's the difference to #11
            width = height;
            height = tmp;

            PlanarYUVLuminanceSource source = CameraManager.get().buildLuminanceSource(rotatedData, width, height);
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
            index++;
//            Log.e(TAG, "decode0000000-------------------------111111---------------------------");
            if (index > 100000) {
                index = 0;
            }

//            try{
//                Thread.sleep(800);
//            }catch (Exception e){
//              e.printStackTrace();
//                Log.e(TAG, "decode---------------------------e=="+e);
//
//            }

            if (index % 2 == 1) {
                //jishu
                Log.e(TAG, "decode1111111111111------------------1111111---------------------------");
                scanBarCode(source, bitmap);
//                bitmap=null;
            } else {
                Log.e(TAG, "decode222222222222222--------------111111111---------------------------");
//                scanBarCode(source, bitmap);
               scanPhoneNum(source.renderCroppedGreyscaleBitmap());





            }


        }

    }



    private void scanBarCode(PlanarYUVLuminanceSource source, BinaryBitmap bitmap){

        Log.e(TAG, "decode1111111111111------------------2222222---------------------------");
        Result rawResult = null;
        try {
            rawResult = multiFormatReader.decodeWithState(bitmap);
        } catch (ReaderException re) {
            // continue
        } finally {
            multiFormatReader.reset();
        }

        Log.e(TAG, "decode1111111111111------------------3333333---------------------------");
        if (rawResult != null) {
            Log.e(TAG, "decode1111111111111------------------4444444---------------------------rawResult=="+rawResult);
            long end = System.currentTimeMillis();
//            Log.d(TAG, "Found barcode (" + (end - start) + " ms):\n" + rawResult.toString());
            Message message = Message.obtain(fragment.getHandler(), R.id.decode_succeeded,1,1, rawResult.getText());
            Bundle bundle = new Bundle();
            bundle.putParcelable(DecodeThread.BARCODE_BITMAP, source.renderCroppedGreyscaleBitmap());
            message.setData(bundle);
            //Log.d(TAG, "Sending decode succeeded message...");
            message.sendToTarget();

            isScanning=false;
        } else {

            Message message = Message.obtain(fragment.getHandler(), R.id.decode_failed);
            message.sendToTarget();

            isScanning=false;

        }
    }




    private  void scanPhoneNum(final Bitmap ssBitmap) {

                    Log.e(TAG, "decode222222222222222----------scanPhoneNum----2222222222---------------------------");
                    try {
//                        Log.d("scantest", "-------------Start------------------");


                        if (null != ssBitmap) {

//                            fragment.setBitmap1(ssBitmap);

                            Mat bapMat = new Mat();
                            Utils.bitmapToMat(ssBitmap, bapMat);

                            // binary image
                            Mat binary = new Mat();
                            Imgproc.cvtColor(bapMat, binary, Imgproc.COLOR_BGR2GRAY);

                            Mat binarymedianBlur = new Mat();
                            Imgproc.medianBlur(binary, binarymedianBlur, 3);

                            Mat bf = new Mat();
                            Imgproc.bilateralFilter(binarymedianBlur, bf, 12, 24, 6);


                            Mat out = new Mat();
                            Imgproc.adaptiveThreshold(bf, out, 255, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY_INV, 27, 10.0d);
                            Mat dst = out.clone();
                            Mat dstF = out.clone();


//                            final Bitmap scanBmp2 = Bitmap.createBitmap(dst.cols(), dst.rows(), Bitmap.Config.ARGB_8888);
//                            Utils.matToBitmap(dst, scanBmp2);
//                            fragment.setBitmap2(ssBitmap);



                            Mat element1 = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(30, 9));
                            Mat element2 = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(24, 4));
                            Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(5, 5));


                            Mat outdilate = new Mat();
                            Point p = new Point(-1, -1);
                            Imgproc.dilate(out, outdilate, element2, p, 1);


//
//                            final Bitmap scanBmp3= Bitmap.createBitmap(outdilate.cols(), outdilate.rows(), Bitmap.Config.ARGB_8888);
//                                Utils.matToBitmap(outdilate, scanBmp3);
//                            fragment.setBitmap3(scanBmp3);



                            Mat outerode = new Mat();
                            Imgproc.erode(outdilate, outerode, element1, p, 1);


//                                final Bitmap scanBmp4= Bitmap.createBitmap(outerode.cols(), outerode.rows(), Bitmap.Config.ARGB_8888);
//                                Utils.matToBitmap(outerode, scanBmp4);
//                                fragment.setBitmap4(scanBmp4);



                            Mat outdilate2 = new Mat();
                            Imgproc.dilate(outerode, outdilate2, element2, p, 1);

//
//                            final Bitmap scanBmp5 = Bitmap.createBitmap(outdilate2.cols(), outdilate2.rows(), Bitmap.Config.ARGB_8888);
//                            Utils.matToBitmap(outdilate2, scanBmp5);
//                            fragment.setBitmap5(scanBmp5);


                            List<MatOfPoint> contours = new ArrayList<>();
                            Mat hireachy = new Mat();
                            Imgproc.findContours(outdilate2, contours, hireachy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE, new Point(0, 0));

//                            Log.e("MainActivity", "findCard--scanPhoneNum -3333333333333333333333333333333333--contours==" + contours.size());
                            if (null == contours&&contours.size()>0) {
                                Message message = Message.obtain(fragment.getHandler(), R.id.decode_failed);
                                message.sendToTarget();
                                isScanning = false;
                                return;
                            }

                            rects = new ArrayList<>();

                            for (int i = 0; i < contours.size(); i++) {
                                org.opencv.core.Rect rect = Imgproc.boundingRect(contours.get(i));
//                                    Imgproc.contourArea(contours.get(i));
                                double area = Imgproc.contourArea(contours.get(i));
//                                Log.e("MainActivity", "findCard--scanPhoneNum-3333333333333333333333333333333333--area==" + area);

                                //找到最小矩形，该矩形可能有方向
                                MatOfPoint matOfPoint = contours.get(i);
                                MatOfPoint2f matOfPoint2f = new MatOfPoint2f(matOfPoint.toArray());

                                double epsilon = 0.001 * Imgproc.arcLength(matOfPoint2f, true);

                                Imgproc.approxPolyDP(matOfPoint2f, matOfPoint2f, epsilon, true);

                                RotatedRect rotatedRectrect = Imgproc.minAreaRect(matOfPoint2f);

                                // 计算高和宽7
                                int m_width = rotatedRectrect.boundingRect().width;

                                int m_height = rotatedRectrect.boundingRect().height;

//                                    Log.e("MainActivity", "findCard---3333333333333333333333333333333333--m_width==" + m_width+"-------------------m_height=="+m_height);

                                if ((m_width > m_height * 6) && m_height > 25) {
                                    int x = rotatedRectrect.boundingRect().x;
                                    int y = rotatedRectrect.boundingRect().y;
                                    int width = rotatedRectrect.boundingRect().width;
                                    int height = rotatedRectrect.boundingRect().height;
//                                    Log.e("MainActivity", "findCard---444444444444--x==" + x + "----------y==" + y + "------------------width==" + width + "------------height==" + height);
                                    if (((y + height) < bapMat.rows()) && ((x + width) < bapMat.cols())) {
                                        Scalar color = new Scalar(255, 255, 255);
                                        Imgproc.rectangle(dst, new Point(x, y), new Point(x + width, y + height), color, 8);
                                        rects.add(rotatedRectrect);
                                    }

                                }


                            }


                            if (null != rects && rects.size() > 0) {

                                for (int i = 0; i < rects.size(); i++) {


                                    int x = rects.get(i).boundingRect().x - 3;
                                    if (x < 0) {
                                        x = 0;
                                    }
                                    int y = rects.get(i).boundingRect().y - 3;
                                    if (y < 0) {
                                        y = 0;
                                    }
                                    int width = rects.get(i).boundingRect().width + 5;
                                    if (width < 0) {
                                        width = 0;
                                    }
                                    int height = rects.get(i).boundingRect().height + 5;
                                    if (height < 0) {
                                        height = 0;
                                    }
//                                    Log.e("MainActivity", "findCard---555555555555555555555555555555555--x==" + x + "----------y==" + y + "------------------width==" + width + "------------height==" + height + "------------------rects==" + rects.size());
                                    org.opencv.core.Rect rect = new org.opencv.core.Rect(x, y, width, height);

                                    Mat caiMat = new Mat(dstF, rect);


                                    final Bitmap scanBmp = Bitmap.createBitmap(caiMat.cols(), caiMat.rows(), Bitmap.Config.ARGB_8888);
                                    Utils.matToBitmap(caiMat, scanBmp);
//
                                    if (null == scanBmp) {
                                        Message message = Message.obtain(fragment.getHandler(), R.id.decode_failed);
                                        message.sendToTarget();
                                        isScanning = false;
                                        return;
                                    }


//                                    fragment.setBitmap6(scanBmp);

//                                    //开始识别
                                    TesseractUtil.getInstance().scanNumber(scanBmp, new SimpleCallback() {
                                        @Override
                                        public void response(String result) {
                                            //这是区域内扫除的所有内容
//                                            Log.e("scantest", "扫描结果：  " + result);

                                            if (!TextUtils.isEmpty(getTelnum(result.replace(" ", "")))) {
                                                //检索结果中是否包含手机号
//                                                Log.e("scantest", "手机号码：  " + getTelnum(result));
                                                Message message = Message.obtain(fragment.getHandler(), R.id.decode_succeeded,2,1, result);
                                                Bundle bundle = new Bundle();
                                                bundle.putParcelable(DecodeThread.BARCODE_BITMAP, ssBitmap);
                                                message.setData(bundle);
                                                //Log.d(TAG, "Sending decode succeeded message...");
                                                message.sendToTarget();

                                                isScanning = false;
                                                Log.e("MainActivity", "findCard--scanPhoneNum------------检索结果中--包含--手机号" );
                                            } else {
                                                Message message = Message.obtain(fragment.getHandler(), R.id.decode_failed);
                                                message.sendToTarget();

                                                isScanning = false;
                                                Log.e("MainActivity", "findCard--scanPhoneNum------------检索结果中--包含--手机号ard--scanPhoneNum------------检索结果中--否包含--手机号" );
                                            }

//
                                            Log.e("scantest", "-------------End------------------");
                                        }
                                    });
//


                                }


                            } else {
                                Message message = Message.obtain(fragment.getHandler(), R.id.decode_failed);
                                message.sendToTarget();
                                isScanning = false;
//                                Log.e("MainActivity", "findCard--scanPhoneNum------------rects.size()==0" );
                            }


                        }
                    } catch (Exception ex) {
                        Log.e("scantest", ex.getMessage());
                        Message message = Message.obtain(fragment.getHandler(), R.id.decode_failed);
                        message.sendToTarget();
                        isScanning = false;
//                        Log.e("MainActivity", "findCard--scanPhoneNum------------Exception ex" );
                    }


    }



    /**
     * 获取字符串中的手机号
     */
    public  String getTelnum(String sParam) {

        if (sParam.length() <= 0) {
            return "";
        }
        if (sParam.length() != 11) {
            return "";
        }

        if (!isNumeric(sParam)) {
            return "";
        }

        Pattern pattern = Pattern.compile("[1|861][3|5|7|8]\\d{9}$*");
        Matcher matcher = pattern.matcher(sParam);
        StringBuffer bf = new StringBuffer();
        while (matcher.find()) {
            bf.append(matcher.group()).append(",");
        }
        int len = bf.length();
        if (len > 0) {
            bf.deleteCharAt(len - 1);
        }
        return sParam;
    }

    public  boolean isNumeric(String str) {

        Pattern pattern = Pattern.compile("[0-9]*");
        Matcher isNum = pattern.matcher(str);

        return isNum.matches();

    }

}
